package game.module.club.logic;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;

import game.HallServer;
import game.common.ErrorCodeConstants;
import game.common.ItemConstants;
import game.entity.PlayingRole;
import game.module.club.bean.Club;
import game.module.club.bean.ClubApply;
import game.module.club.bean.ClubCodeBean;
import game.module.club.bean.ClubDonateDetail;
import game.module.club.bean.ClubInviteBean;
import game.module.club.bean.ClubMember;
import game.module.club.dao.ClubCache;
import game.module.club.dao.ClubDao;
import game.module.club.dao.ClubNameTemplateCache;
import game.module.club.dao.ClubUpTemplateCache;
import game.module.item.bean.Item;
import game.module.item.dao.ItemCache;
import game.module.item.logic.ItemManager;
import game.module.mail.logic.MailManager;
import game.module.offline.bean.PlayerOfflineCache;
import game.module.offline.logic.PlayerOfflineManager;
import game.module.template.ClubNameTemplate;
import game.module.template.ClubUpTemplate;
import game.module.user.bean.PlayerAddressBean;
import game.module.user.bean.PlayerBean;
import game.module.user.dao.PlayerDao;
import game.module.user.logic.PlayerDaoHelper;
import game.session.PlayerOnlineCacheMng;
import game.session.SessionManager;
import game.util.CommUtil;
import game.util.DateKit;
import game.util.YunPianUtil;
import lua.LuaMessageHall.C2SClubCreate;
import lua.LuaMessageHall.ClubApplyMember;
import lua.LuaMessageHall.ClubCreditNum;
import lua.LuaMessageHall.ClubInfo;
import lua.LuaMessageHall.ClubManageMember;
import lua.LuaMessageHall.ClubMemberDetail;
import lua.LuaMessageHall.JinDouDetail;
import lua.LuaMessageHall.S2CClubApply;
import lua.LuaMessageHall.S2CClubApplyList;
import lua.LuaMessageHall.S2CClubAppoint;
import lua.LuaMessageHall.S2CClubCreate;
import lua.LuaMessageHall.S2CClubDonate;
import lua.LuaMessageHall.S2CClubInfo;
import lua.LuaMessageHall.S2CClubInviteList;
import lua.LuaMessageHall.S2CClubJinDouDetail;
import lua.LuaMessageHall.S2CClubList;
import lua.LuaMessageHall.S2CClubMakeOver;
import lua.LuaMessageHall.S2CClubManageChange;
import lua.LuaMessageHall.S2CClubManageList;
import lua.LuaMessageHall.S2CClubMember;
import lua.LuaMessageHall.S2CClubModifyWeixin;
import lua.LuaMessageHall.S2CClubPushStauts;
import lua.LuaMessageHall.S2CClubRaisedAct;
import lua.LuaMessageHall.S2CClubRaisedFind;
import lua.LuaMessageHall.S2CClubUp;

/**
 * @author: Pomelo.Lee
 * @date: 2017年8月29日 上午10:53:43
 */
public class ClubManager {

	private static Logger logger = LoggerFactory.getLogger(ClubManager.class);

	static class SingletonHolder {
		static ClubManager instance = new ClubManager();
	}

	public static ClubManager getInstance() {
		return SingletonHolder.instance;
	}

	/**
	 * 登录增加俱乐部活跃度
	 */
	public void loginClubAddlivenessNum(PlayingRole pr) {
		if (pr == null || pr.getPlayerBean() == null || pr.getPlayerBean().getClub_id() <= 0) {
			return;
		}
		Date last = pr.getPlayerBean().getDownlineTime();
		if (last != null && DateUtils.isSameDay(last, new Date())) {
			return;
		}
		addlivenessNum(pr.getPlayerBean().getClub_id(), 1);
	}

	/**
	 * 消耗钻石增加活跃度
	 * 
	 * @param pr
	 * @param fangka
	 */
	public void expenseFangKaAddlivenessNum(PlayingRole pr, int fangka) {
		if (pr == null || pr.getPlayerBean() == null || pr.getPlayerBean().getClub_id() <= 0) {
			return;
		}
		if (fangka <= 0) {
			return;
		}
		addlivenessNum(pr.getPlayerBean().getClub_id(), fangka);
	}

	private void addlivenessNum(int clubId, int num) {
		logger.info(" addlivenessNum  clubId={},num={}", clubId, num);
		if (num <= 0) {
			return;
		}
		Club club = ClubCache.getInstance().getClubById(clubId);
		if (club == null) {
			return;
		}
		club.setLiveNessNum(club.getLiveNessNum() + num);
		// 重新排行及 DB到数据库
		ClubCache.getInstance().rankClub();
		ClubDaoHelper.getInstance().asyncUpdateClubBean(club);
	}

	/**
	 * 拒绝邀请加入俱乐部
	 * 
	 * @param playingRole
	 * @param clubId
	 * @return
	 */
	public int rejectInvite(PlayingRole playingRole, int clubId) {
		int playerId = playingRole.getId();
		ClubInviteBean clubInvite = ClubCache.getInstance().getInviteBeanByPlayerId(playerId, clubId);
		if (clubInvite != null && clubInvite.getStatus() == 0) {
			// 0.邀请中 1.已同意 2.已经拒绝
			clubInvite.setStatus(2);
			ClubDaoHelper.getInstance().asyncUpdateClubInvite(clubInvite.getId(), 2);
		}
		return 1;
	}

	/**
	 * 同意俱乐部邀请加入俱乐部
	 * 
	 * @param playingRole
	 * @param clubId
	 * @return
	 */
	public int agreeInvite(PlayingRole playingRole, int clubId) {
		int oldClubId = playingRole.getPlayerBean().getClub_id();
		Club oldClub = ClubCache.getInstance().getClubById(oldClubId);
		if (oldClub != null) {
			return ErrorCodeConstants.HALL_CLUB_AMID;
		}
		Club club = ClubCache.getInstance().getClubById(clubId);
		if (club == null) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		int playerId = playingRole.getId();
		ClubInviteBean clubInvite = ClubCache.getInstance().getInviteBeanByPlayerId(playerId, clubId);
		if (clubInvite == null || clubInvite.getStatus() != 0) {
			return ErrorCodeConstants.HALL_CLUB_AMID;
		}
		int curNum = club.getMapMember().size();
		ClubUpTemplate template = ClubUpTemplateCache.getInstance().getTemplate(club.getLevel());
		int residue_num = template.getMaxnum() - curNum;
		if (1 > residue_num) {
			return ErrorCodeConstants.HALL_CLUB_MAX_MEMBER;
		}

		PlayerBean playerBean = playingRole.getPlayerBean();
		club.setNum(club.getNum() + 1);
		addClubMember(club, playerBean, 0);
		playerBean.setClub_id(clubId);
		PlayerDaoHelper.getInstance().asyncUpdatePlayerBean(playerBean);
		clubInvite.setStatus(1);
		ClubDaoHelper.getInstance().asyncUpdateClubInvite(clubInvite.getId(), 1);

		return 1;
	}

	/**
	 * 邀请加入俱乐部
	 * 
	 * @param playingRole
	 * @param ids
	 * @return
	 */
	public int clubInvite(PlayingRole playingRole, int[] ids) {
		int clubId = playingRole.getPlayerBean().getClub_id();
		if (clubId <= 0) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		Club club = ClubCache.getInstance().getClubById(clubId);
		if (club == null) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		int playerId = playingRole.getId();
		ClubMember cm = club.getMapMember().get(playerId);
		if (cm == null || cm.getAuth() == 0) { // 权限：0.普通成员 1.副会长 2.会长
			return ErrorCodeConstants.HALL_CLUB_NO_AUTH;
		}
		Map<Integer, ClubMember> map = club.getMapMember();
		List<Integer> listIds = new ArrayList<>();
		for (int id : ids) {
			if (map.containsKey(id)) {
				logger.info("club invite exist in playerid={}", id);
				continue;
			}
			if (ClubCache.getInstance().isContainsInvite(id, clubId)) {
				continue;
			}
			ClubInviteBean bean = new ClubInviteBean();
			bean.setClubId(clubId);
			bean.setCreateTime(new Date());
			bean.setPlayerId(id);
			bean.setStatus(0);
			ClubDaoHelper.getInstance().asyncSaveClubInvite(bean);
			listIds.add(id);
			ClubCache.getInstance().addInviteBean(bean);
		}

		// send mail invite
		Map<String, String> params = new HashMap<>();
		params.put("$1", DateKit.formateDateToStr(new Date()));
		params.put("$2", club.getName());
		params.put("$3", getAuthName(cm.getAuth()));
		params.put("$4", cm.getPlayerName());
		params.put("$5", club.getName());

		Map<String, Object> map_club = new HashMap<>();
		map_club.put("act_type", 1);
		map_club.put("clubId", clubId);
		map_club.put("clubName", club.getName());
		params.put("$OTHER", JSON.toJSONString(map_club));

		MailManager.getInstance().asyncendMailToPlayerList(listIds.toArray(new Integer[0]), MailManager.MAIL_CLUB_INVITE_ID, params, null);

		return 1;
	}

	/**
	 * 邀请加入俱乐部的成员列表
	 * 
	 * @param playingRole
	 * @return
	 */
	public int clubInviteList(PlayingRole playingRole, S2CClubInviteList respMsg) {
		int clubId = playingRole.getPlayerBean().getClub_id();
		if (clubId <= 0) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		Club club = ClubCache.getInstance().getClubById(clubId);
		if (club == null) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		int playerId = playingRole.getId();
		ClubMember cm = club.getMapMember().get(playerId);
		if (cm == null || cm.getAuth() == 0) { // 权限：0.普通成员 1.副会长 2.会长
			return ErrorCodeConstants.HALL_CLUB_NO_AUTH;
		}
		List<ClubApplyMember> list = new ArrayList<>();
		String lat = "30.620076";
		String lng = "104.067221";
		PlayerAddressBean address = PlayerDao.getInstance().getPlayerAddressByPlayerId(playerId);
		if (address != null) {
			lat = address.getLat();
			lng = address.getLng();
		} else {
			respMsg.apply_list = list.toArray(new ClubApplyMember[0]);
			return 1;
		}

		List<PlayerAddressBean> addressList = PlayerDao.getInstance().findNearbyList(lat, lng, 10, 20);
		if (addressList != null && addressList.size() > 0) {
			for (PlayerAddressBean pab : addressList) {
				if (pab.getPlayerId() == playerId) {
					continue;
				}
				packClubApplyMember(pab.getPlayerId(), list, pab, true, clubId);
			}
		}
		respMsg.apply_list = list.toArray(new ClubApplyMember[0]);
		return 1;
	}

	/**
	 * 拒绝加入俱乐部
	 * 
	 * @param playingRole
	 * @param ids
	 * @return
	 */
	public int rejectApply(PlayingRole playingRole, int[] ids) {
		int clubId = playingRole.getPlayerBean().getClub_id();
		if (clubId <= 0) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		Club club = ClubCache.getInstance().getClubById(clubId);
		if (club == null) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		int playerId = playingRole.getId();
		ClubMember cm = club.getMapMember().get(playerId);
		if (cm == null || cm.getAuth() == 0) { // 权限：0.普通成员 1.副会长 2.会长
			return ErrorCodeConstants.HALL_CLUB_NO_AUTH;
		}
		Integer[] pids = new Integer[ids.length];
		int i = 0;
		for (int applyiId : ids) {
			ClubCache.getInstance().rejectApplyPlayerId(clubId, applyiId);
			ClubDaoHelper.getInstance().asyncDelClubApplyByPlayerIdAndClubId(applyiId, clubId);
			pids[i] = applyiId;
			i++;
		}
		// 俱乐部加入申请未通过 send mail
		Map<String, String> params = new HashMap<>();
		params.put("$1", club.getName());
		MailManager.getInstance().asyncendMailToPlayerList(pids, MailManager.MAIL_APPLY_REJECT_ID, params, null);

		return 1;
	}

	/**
	 * 同意加入俱乐部
	 * 
	 * @param playingRole
	 * @param ids
	 * @return
	 */
	public int agreeApply(PlayingRole playingRole, int[] ids) {
		int clubId = playingRole.getPlayerBean().getClub_id();
		if (clubId <= 0) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		Club club = ClubCache.getInstance().getClubById(clubId);
		if (club == null) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		int playerId = playingRole.getId();
		ClubMember cm = club.getMapMember().get(playerId);
		if (cm == null || cm.getAuth() == 0) { // 权限：0.普通成员 1.副会长 2.会长
			return ErrorCodeConstants.HALL_CLUB_NO_AUTH;
		}
		int curNum = club.getMapMember().size();
		ClubUpTemplate template = ClubUpTemplateCache.getInstance().getTemplate(club.getLevel());
		int residue_num = template.getMaxnum() - curNum;
		if (ids.length > residue_num) {
			return ErrorCodeConstants.HALL_CLUB_MAX_MEMBER;
		}
		Map<Integer, ClubApply> map = ClubCache.getInstance().getClubApplyMap(clubId);
		if (map == null || map.size() < ids.length) {
			return ErrorCodeConstants.CLUB_APPLY_PROCESSED;
		}

		// cheack applyId 条件
		List<PlayerBean> list = new ArrayList<>();
		Map<Integer, PlayingRole> mapOnline = new ConcurrentHashMap<>();
		for (int applyId : ids) {
			PlayingRole pr = SessionManager.getInstance().getPlayer(applyId);
			PlayerBean playerBean = null;
			if (pr != null) {
				mapOnline.put(pr.getId(), pr);
				playerBean = pr.getPlayerBean();
			} else {
				playerBean = PlayerDao.getInstance().getPlayerById(applyId);
			}
			if (playerBean == null) {
				logger.error("not found playerid={}", applyId);
				return ErrorCodeConstants.HALL_CLUB_AMID;
			}
			if (playerBean.getClub_id() > 0) {
				logger.error("adid add club playerid={},clubId={}", applyId, playerBean.getClub_id());
				return ErrorCodeConstants.HALL_CLUB_AMID;
			}
			list.add(playerBean);
		}

		for (PlayerBean playerBean : list) {
			club.setNum(club.getNum() + 1);
			addClubMember(club, playerBean, 0);
			playerBean.setClub_id(clubId);
			ClubCache.getInstance().removeApplyPlayerId(clubId, playerBean.getId());
			PlayerDaoHelper.getInstance().asyncUpdatePlayerBean(playerBean);
			ClubDaoHelper.getInstance().asynDelClubApplyByPlayerId(playerBean.getId());
			// send mail 同时邮件发送给申请玩家
			Map<String, String> params = new HashMap<>();
			params.put("$1", club.getName());
			MailManager.getInstance().sendMailSigleToPlayer(playerBean.getId(), MailManager.MAIL_APPLY_AGREE_ID, params, null);
		}
		if (mapOnline.size() > 0) {
			for (PlayingRole pr : mapOnline.values()) {
				S2CClubPushStauts respMsg = new S2CClubPushStauts();
				respMsg.club_id = clubId;
				pr.writeAndFlush(respMsg.build(pr.alloc()));
			}
		}
		return 1;
	}

	private void addClubMember(Club club, PlayerBean playerBean, int auth) {
		ClubMember clubMember = new ClubMember();
		clubMember.setAuth(auth); // 权限：0.普通成员 1.副会长 2.会长
		clubMember.setClubId(club.getId());
		clubMember.setCreateTime(new Date());
		clubMember.setCredit_num(0);
		clubMember.setHeadimg(playerBean.getHeadimg());
		clubMember.setPlayerId(playerBean.getId());
		clubMember.setPlayerName(playerBean.getName());
		club.getMapMember().put(clubMember.getPlayerId(), clubMember);
		ClubDaoHelper.getInstance().asyncSaveClubMember(clubMember);
	}

	/**
	 * 申请加入俱乐部的列表
	 * 
	 * @param playingRole
	 * @param respMsg
	 * @return
	 */
	public int clubApplyList(PlayingRole playingRole, S2CClubApplyList respMsg) {
		int clubId = playingRole.getPlayerBean().getClub_id();
		if (clubId <= 0) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		Club club = ClubCache.getInstance().getClubById(clubId);
		if (club == null) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		int playerId = playingRole.getId();
		ClubMember cm = club.getMapMember().get(playerId);
		if (cm == null || cm.getAuth() == 0) { // 权限：0.普通成员 1.副会长 2.会长
			return ErrorCodeConstants.HALL_CLUB_NO_AUTH;
		}
		Map<Integer, ClubApply> map = ClubCache.getInstance().getClubApplyMap(clubId);
		List<ClubApplyMember> list = new ArrayList<>();
		if (map != null) {
			for (ClubApply ca : map.values()) {
				packClubApplyMember(ca.getPlayerId(), list, null, false, clubId);
			}
		}

		int curNum = club.getMapMember().size();
		ClubUpTemplate template = ClubUpTemplateCache.getInstance().getTemplate(club.getLevel());
		respMsg.residue_num = template.getMaxnum() - curNum;
		respMsg.apply_list = list.toArray(new ClubApplyMember[0]);
		return 1;
	}

	public void packClubApplyMember(int playerId, List<ClubApplyMember> list, PlayerAddressBean address, boolean isInvite, int clubId) {
		ClubApplyMember cam = new ClubApplyMember();
		PlayingRole pr = SessionManager.getInstance().getPlayer(playerId);
		int status = 2;
		PlayerBean playerBean = null;
		if (pr != null) {
			status = 1;
			playerBean = pr.getPlayerBean();
		} else {
			playerBean = PlayerDao.getInstance().getPlayerById(playerId);
		}
		if (playerBean == null) {
			logger.error("not found playerid={}", playerId);
			return;
		}
		if (playerBean.getClub_id() > 0 && !isInvite) {
			// 清除已经存在的申请数据
			ClubCache.getInstance().rejectApplyPlayerId(clubId, playerBean.getId());
			ClubDaoHelper.getInstance().asyncDelClubApplyByPlayerIdAndClubId(playerBean.getId(), clubId);
			return;
		}
		String clubName = "";
		if (playerBean.getClub_id() > 0) {
			Club club = ClubCache.getInstance().getClubById(playerBean.getClub_id());
			clubName = club != null ? club.getName() : "";
		}
		if (address == null) {
			address = PlayerDao.getInstance().getPlayerAddressByPlayerId(playerId);
		}
		int downlineTime = 0;
		if (playerBean.getDownlineTime() != null) {
			downlineTime = (int) ((System.currentTimeMillis() - playerBean.getDownlineTime().getTime()) / 1000);
		}
		cam.headimg = playerBean.getHeadimg();
		cam.downline_time = downlineTime;
		cam.lat = address != null ? address.getLat() : "";
		cam.lng = address != null ? address.getLng() : "";
		cam.player_id = playerId;
		cam.player_name = playerBean.getName();
		cam.status = status; // 1.在线 2.离线
		cam.club_name = clubName;
		cam.invite_status = -1; // 状态 -1 是未邀请 0.邀请中 1.已同意 2.已经拒绝
		if (isInvite) {
			ClubInviteBean inviteBean = ClubCache.getInstance().getInviteBeanByPlayerId(playerId, clubId);
			if (inviteBean != null) {
				cam.invite_status = inviteBean.getStatus();
			}
		}
		list.add(cam);
	}

	/**
	 * 俱乐部解散
	 * 
	 * @param playingRole
	 * @return
	 */
	public int dissolve(PlayingRole playingRole) {
		int clubId = playingRole.getPlayerBean().getClub_id();
		if (clubId <= 0) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		Club club = ClubCache.getInstance().getClubById(clubId);
		if (club == null) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		int playerId = playingRole.getId();
		ClubMember cm = club.getMapMember().get(playerId);
		// 会长权限 // 权限：0.普通成员 1.副会长 2.会长
		if (cm == null || cm.getAuth() != 2) {
			return ErrorCodeConstants.HALL_CLUB_NO_AUTH;
		}
		club.setDelFlag(1);
		club.setDleTime(new Date());

		playingRole.getPlayerBean().setClub_id(0);
		ClubCache.getInstance().removeClub(clubId);

		ClubDaoHelper.getInstance().asyncDelClubBean(club);

		for (int tempPlayerId : club.getMapMember().keySet()) {
			PlayingRole pr = SessionManager.getInstance().getPlayer(tempPlayerId);
			if (pr != null) {
				pr.getPlayerBean().setClub_id(0);
				S2CClubPushStauts respMsg = new S2CClubPushStauts();
				respMsg.club_id = 0;
				pr.writeAndFlush(respMsg.build(pr.alloc()));
			}
			PlayerDaoHelper.getInstance().asyncPlayerBeanExitClub(tempPlayerId);
		}
		ClubDaoHelper.getInstance().asyncDissolveClubMember(clubId);

		// 发送邮件给所有人
		Map<String, String> params = new HashMap<>();
		params.put("$1", DateKit.formateDateToStr(new Date()));
		params.put("$2", club.getName());
		params.put("$3", cm.getPlayerName());
		params.put("$4", club.getName());
		Integer[] playerIds = club.getMapMember().keySet().toArray(new Integer[0]);
		MailManager.getInstance().asyncendMailToPlayerList(playerIds, MailManager.MAIL_CLUB_DISSOLVE_ID, params, null);

		return 1;
	}

	/**
	 * 俱乐部转让
	 * 
	 * @param playingRole
	 * @param toPlayerId
	 * @return
	 */
	public int makeOver(PlayingRole playingRole, int toPlayerId, S2CClubMakeOver respMsg) {
		int clubId = playingRole.getPlayerBean().getClub_id();
		if (clubId <= 0) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		Club club = ClubCache.getInstance().getClubById(clubId);
		if (club == null) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		int playerId = playingRole.getId();
		ClubMember cm = club.getMapMember().get(playerId);
		// 会长权限 // 权限：0.普通成员 1.副会长 2.会长
		if (cm == null || cm.getAuth() != 2 || toPlayerId == club.getCdrId()) {
			return ErrorCodeConstants.HALL_CLUB_NO_AUTH;
		}

		ClubMember toCm = club.getMapMember().get(toPlayerId);
		if (toCm == null) {
			return ErrorCodeConstants.HALL_CLUB_MEMBER_NOT_FOUND;
		}

		club.setCdrId(toCm.getPlayerId());
		club.setCdrName(toCm.getPlayerName());
		club.setCdrWeixin("");

		cm.setAuth(0);
		toCm.setAuth(2);

		ClubDaoHelper.getInstance().asyncUpdateClubBean(club);
		ClubDaoHelper.getInstance().asynUpdateClubMember(cm);
		ClubDaoHelper.getInstance().asynUpdateClubMember(toCm);

		// send mail club member
		Map<String, String> params = new HashMap<>();
		params.put("$1", DateKit.formateDateToStr(new Date()));
		params.put("$2", club.getName());
		params.put("$3", cm.getPlayerName());
		params.put("$4", toCm.getPlayerName());
		Integer[] playerIds = club.getMapMember().keySet().toArray(new Integer[0]);
		MailManager.getInstance().asyncendMailToPlayerList(playerIds, MailManager.MAIL_CLUB_MAKEOVER_ID, params, null);

		respMsg.player_name = toCm.getPlayerName();
		return 1;
	}

	/**
	 * 更换副会长
	 * 
	 * @param playingRole
	 * @param toPlayerId
	 * @param toOtherPlayerId
	 * @return
	 */
	public int manageChange(PlayingRole playingRole, int toPlayerId, int toOtherPlayerId, S2CClubManageChange respMsg) {
		int clubId = playingRole.getPlayerBean().getClub_id();
		if (clubId <= 0) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		Club club = ClubCache.getInstance().getClubById(clubId);
		if (club == null) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		int playerId = playingRole.getId();
		ClubMember cm = club.getMapMember().get(playerId);
		// 会长权限 // 权限：0.普通成员 1.副会长 2.会长
		if (cm == null || cm.getAuth() != 2 || toOtherPlayerId == club.getCdrId()) {
			return ErrorCodeConstants.HALL_CLUB_NO_AUTH;
		}
		ClubMember toCm = club.getMapMember().get(toPlayerId);
		ClubMember toOtherCm = club.getMapMember().get(toOtherPlayerId);
		if (toCm == null || toOtherCm == null) {
			return ErrorCodeConstants.HALL_CLUB_MEMBER_NOT_FOUND;
		}
		if (toOtherCm.getAuth() == 1) {
			return ErrorCodeConstants.HALL_CLUB_YET_MANAGE;
		}
		if (toCm.getAuth() != 1) {
			return ErrorCodeConstants.HALL_CLUB_NO_AUTH;
		}
		toCm.setAuth(0);
		toOtherCm.setAuth(1);

		ClubDaoHelper.getInstance().asynUpdateClubMember(toCm);
		ClubDaoHelper.getInstance().asynUpdateClubMember(toOtherCm);

		respMsg.player_name = toCm.getPlayerName();
		respMsg.to_player_name = toOtherCm.getPlayerName();

		return 1;
	}

	/**
	 * 副会长任命
	 * 
	 * @param playingRole
	 * @param toPlayerId
	 * @return
	 */
	public int appoint(PlayingRole playingRole, int toPlayerId, S2CClubAppoint respMsg) {
		int clubId = playingRole.getPlayerBean().getClub_id();
		if (clubId <= 0) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		Club club = ClubCache.getInstance().getClubById(clubId);
		if (club == null) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		int playerId = playingRole.getId();
		ClubMember cm = club.getMapMember().get(playerId);
		// 会长权限 // 权限：0.普通成员 1.副会长 2.会长
		if (cm == null || cm.getAuth() != 2 || toPlayerId == club.getCdrId()) {
			return ErrorCodeConstants.HALL_CLUB_NO_AUTH;
		}

		ClubMember toCm = club.getMapMember().get(toPlayerId);
		if (toCm == null) {
			return ErrorCodeConstants.HALL_CLUB_MEMBER_NOT_FOUND;
		}
		if (toCm.getAuth() == 1) {
			return 1;
		}
		toCm.setAuth(1);
		ClubDaoHelper.getInstance().asynUpdateClubMember(toCm);

		respMsg.player_name = toCm.getPlayerName();
		return 1;
	}

	/**
	 * 俱乐部管理员列表
	 * 
	 * @param playingRole
	 * @param respMsg
	 * @return
	 */
	public int manageList(PlayingRole playingRole, S2CClubManageList respMsg) {
		int clubId = playingRole.getPlayerBean().getClub_id();
		if (clubId <= 0) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		Club club = ClubCache.getInstance().getClubById(clubId);
		if (club == null) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		int playerId = playingRole.getId();
		ClubMember cm = club.getMapMember().get(playerId);
		// 会长权限
		if (cm == null || cm.getAuth() != 2) { // 权限：0.普通成员 1.副会长 2.会长
			return ErrorCodeConstants.HALL_CLUB_NO_AUTH;
		}
		Collection<ClubMember> list = club.getMapMember().values();
		List<ClubManageMember> respList = new ArrayList<>();
		for (ClubMember cmember : list) {
			if (cmember.getAuth() != 1) {
				continue;
			}
			ClubManageMember cmm = new ClubManageMember();
			cmm.player_id = cmember.getPlayerId();
			cmm.player_name = cmember.getPlayerName();
			respList.add(cmm);
		}
		respMsg.manage_list = respList.toArray(new ClubManageMember[0]);
		return 1;
	}

	/**
	 * 踢出俱乐部成员
	 * 
	 * @param playingRole
	 * @param plauerIds
	 * @return
	 */
	public int kickMemberClub(PlayingRole playingRole, int[] plauerIds) {
		int clubId = playingRole.getPlayerBean().getClub_id();
		if (clubId <= 0) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		Club club = ClubCache.getInstance().getClubById(clubId);
		if (club == null) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		int playerId = playingRole.getId();
		ClubMember cm = club.getMapMember().get(playerId);
		if (cm == null || cm.getAuth() == 0) { // 权限：0.普通成员 1.副会长 2.会长
			return ErrorCodeConstants.HALL_CLUB_NO_AUTH;
		}
		List<ClubMember> list = new ArrayList<>();
		int state = checkClubMemberKick(plauerIds, list, club, playingRole.getId());
		if (state != 1) {
			return state;
		}
		Integer[] playerIds = new Integer[list.size()];
		int i = 0;

		for (ClubMember cmember : list) {
			club.getMapMember().remove(cmember.getPlayerId());
			ClubDaoHelper.getInstance().asyncDelClubMemberByPlayerId(cmember.getPlayerId());
			// 设置俱乐部的id为0
			PlayingRole pr = SessionManager.getInstance().getPlayer(cmember.getPlayerId());
			if (pr != null) {
				pr.getPlayerBean().setClub_id(0);
				S2CClubPushStauts respMsg = new S2CClubPushStauts();
				respMsg.club_id = 0;
				pr.writeAndFlush(respMsg.build(pr.alloc()));
			}
			PlayerDaoHelper.getInstance().asyncPlayerBeanExitClub(cmember.getPlayerId());

			playerIds[i] = cmember.getPlayerId();
			i++;
		}
		// send mail 批量踢人
		Map<String, String> params = new HashMap<>();
		params.put("$1", DateKit.formateDateToStr(new Date()));
		params.put("$2", getAuthName(cm.getAuth()));
		params.put("$3", cm.getPlayerName());
		params.put("$4", club.getName());
		MailManager.getInstance().asyncendMailToPlayerList(playerIds, MailManager.MAIL_CLUB_KICK_ID, params, null);
		return 1;
	}

	private int checkClubMemberKick(int[] plauerIds, List<ClubMember> list, Club club, int curPlayerId) {
		for (int toPlayerId : plauerIds) {
			ClubMember toCm = club.getMapMember().get(toPlayerId);
			if (toCm == null) {
				return ErrorCodeConstants.HALL_CLUB_MEMBER_NOT_FOUND;
			}
			if (curPlayerId == toPlayerId || toPlayerId == club.getCdrId()) {
				return ErrorCodeConstants.HALL_CLUB_NO_AUTH;
			}
			list.add(toCm);
		}

		return 1;
	}

	/**
	 * 修改成员的信用分
	 * 
	 * @param playingRole
	 * @param toPlayerId
	 * @param creditNum
	 * @return
	 */
	public int modifyCreditNum(PlayingRole playingRole, ClubCreditNum[] creditNums) {
		int clubId = playingRole.getPlayerBean().getClub_id();
		if (clubId <= 0) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		Club club = ClubCache.getInstance().getClubById(clubId);
		if (club == null) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		int playerId = playingRole.getId();
		ClubMember cm = club.getMapMember().get(playerId);
		if (cm == null || cm.getAuth() == 0) { // 权限：0.普通成员 1.副会长 2.会长
			return ErrorCodeConstants.HALL_CLUB_NO_AUTH;
		}
		for (ClubCreditNum cn : creditNums) {
			ClubMember toCm = club.getMapMember().get(cn.player_id);
			if (toCm == null) {
				return ErrorCodeConstants.HALL_CLUB_MEMBER_NOT_FOUND;
			}
		}
		int creditNum = 0;
		for (ClubCreditNum cn : creditNums) {
			ClubMember toCm = club.getMapMember().get(cn.player_id);
			creditNum = cn.credit_num;
			creditNum = creditNum > 1000 ? 1000 : creditNum;
			creditNum = creditNum < 0 ? 0 : creditNum;
			toCm.setCredit_num(creditNum);
			ClubDaoHelper.getInstance().asynUpdateClubMember(toCm);
			// send mail to toplayerid
			Map<String, String> params = new HashMap<>();
			params.put("$1", DateKit.formateDateToStr(new Date()));
			params.put("$2", getAuthName(cm.getAuth()));
			params.put("$3", playingRole.getPlayerBean().getName());
			params.put("$4", creditNum + "");
			MailManager.getInstance().sendMailSigleToPlayer(cn.player_id, MailManager.MAIL_CLUB_CREDIT_ID, params, null);
		}
		return 1;
	}

	/**
	 * 权限转换成中文名称
	 * 
	 * @param auth
	 * @return
	 */
	private String getAuthName(int auth) {
		switch (auth) {
		case 2:
			return "会长";
		case 1:
			return "副会长";
		case 0:
			return "成员";
		default:
			return "";
		}
	}

	/**
	 * 封赏金豆
	 * 
	 * @param playingRole
	 * @param toPlayerId
	 * @param jinDouNum
	 * @param respMsg
	 * @return
	 */
	public int raisedJiuDouActClub(PlayingRole playingRole, int toPlayerId, long jinDouNum, S2CClubRaisedAct respMsg) {
		if (jinDouNum <= 0) {
			return ErrorCodeConstants.SYS_REQ_PAR;
		}
		int clubId = playingRole.getPlayerBean().getClub_id();
		if (clubId <= 0) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		Club club = ClubCache.getInstance().getClubById(clubId);
		if (club == null) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		int playerId = playingRole.getId();
		ClubMember cm = club.getMapMember().get(playerId);
		if (cm == null || cm.getAuth() == 0) { // 权限：0.普通成员 1.副会长 2.会长
			return ErrorCodeConstants.HALL_CLUB_NO_AUTH;
		}
		ClubMember toCm = club.getMapMember().get(toPlayerId);
		if (toCm == null) {
			return ErrorCodeConstants.HALL_CLUB_MEMBER_NOT_FOUND;
		}
		if (club.getJinDou() < jinDouNum) {
			return ErrorCodeConstants.HALL_NO_ENOUGH_JIN_DOU;
		}

		club.setJinDou(club.getJinDou() - jinDouNum);

		ClubDaoHelper.getInstance().asyncUpdateClubBean(club);

		PlayingRole pr = SessionManager.getInstance().getPlayer(toCm.getPlayerId());
		if (pr != null) {
			ItemManager.getInstance().addItem(pr, ItemConstants.YUANBAO_ITEM_ID, (int) jinDouNum, toCm.getPlayerId());
		} else {
			// 离线增加 金豆
			PlayerDaoHelper.getInstance().asyncAddJinDouForPlayerBean(toPlayerId, jinDouNum);
		}

		ClubDonateDetail donateDetail = new ClubDonateDetail();
		Date now = new Date();
		donateDetail.setAct(2);
		donateDetail.setActJinDou(jinDouNum);
		donateDetail.setClubId(clubId);
		donateDetail.setCreateTime(now);
		donateDetail.setPlayerId(toCm.getPlayerId());
		donateDetail.setPlayerName(toCm.getPlayerName());
		donateDetail.setRetainJinDou(club.getJinDou());
		donateDetail.setActPlayerId(playingRole.getId());
		donateDetail.setActPlayerName(playingRole.getPlayerBean().getName());

		ClubCache.getInstance().addClubDonateDetail(donateDetail);
		ClubDaoHelper.getInstance().asyncSaveClubDonateDetail(donateDetail);

		respMsg.jin_dou_detail = packJinDouDetail(donateDetail);

		// mail 同时系统发送邮件到自己（副会长）及俱乐部会长和目标玩家
		Map<String, String> params = new HashMap<>();
		params.put("$1", DateKit.formateDateToStr(new Date()));
		params.put("$2", getAuthName(cm.getAuth()));
		params.put("$3", playingRole.getPlayerBean().getName());
		params.put("$4", toCm.getPlayerName());
		params.put("$5", jinDouNum + "");

		Set<Integer> setMailIds = new HashSet<Integer>();
		setMailIds.add(playerId);
		setMailIds.add(toPlayerId);
		setMailIds.add(club.getCdrId());
		Integer[] playerIds = setMailIds.toArray(new Integer[0]);
		MailManager.getInstance().asyncendMailToPlayerList(playerIds, MailManager.MAIL_CLUB_RAISED_ID, params, null);

		return 1;
	}

	private JinDouDetail packJinDouDetail(ClubDonateDetail donateDetail) {
		JinDouDetail jdd = new JinDouDetail();
		jdd.act = donateDetail.getAct();
		jdd.act_jin_dou = donateDetail.getActJinDou();
		jdd.club_id = donateDetail.getClubId();
		jdd.player_id = donateDetail.getPlayerId();
		jdd.player_name = donateDetail.getPlayerName();
		jdd.retain_jin_dou = donateDetail.getRetainJinDou();
		jdd.time = (int) (donateDetail.getCreateTime().getTime() / 1000L);
		return jdd;
	}

	/**
	 * 封赏金豆给俱乐部成员
	 * 
	 * @param playingRole
	 * @param toPlayerId
	 * @param respMsg
	 * @return
	 */
	public int raisedFindClub(PlayingRole playingRole, int toPlayerId, S2CClubRaisedFind respMsg) {
		int clubId = playingRole.getPlayerBean().getClub_id();
		if (clubId <= 0) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		Club club = ClubCache.getInstance().getClubById(clubId);
		if (club == null) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		int playerId = playingRole.getId();
		ClubMember cm = club.getMapMember().get(playerId);
		if (cm == null || cm.getAuth() == 0) { // 权限：0.普通成员 1.副会长 2.会长
			return ErrorCodeConstants.HALL_CLUB_NO_AUTH;
		}
		ClubMember toCm = club.getMapMember().get(toPlayerId);
		if (toCm == null) {
			return ErrorCodeConstants.HALL_CLUB_MEMBER_NOT_FOUND;
		}

		respMsg.player_name = toCm.getPlayerName();

		return 1;
	}

	/**
	 * 修改公告
	 * 
	 * @param playingRole
	 * @param notice
	 * @return
	 */
	public int modifyClubNotice(PlayingRole playingRole, String notice) {
		int clubId = playingRole.getPlayerBean().getClub_id();
		if (clubId <= 0) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		Club club = ClubCache.getInstance().getClubById(clubId);
		if (club == null) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		int playerId = playingRole.getId();
		ClubMember cm = club.getMapMember().get(playerId);
		if (cm == null || cm.getAuth() == 0) { // 权限：0.普通成员 1.副会长 2.会长
			return ErrorCodeConstants.HALL_CLUB_NO_AUTH;
		}

		club.setNotice(notice);
		ClubDaoHelper.getInstance().asyncUpdateClubBean(club);

		return 1;
	}

	/**
	 * 升级
	 * 
	 * @param playingRole
	 * @param respMsg
	 * @return
	 */
	public int upClub(PlayingRole playingRole, S2CClubUp respMsg) {
		int clubId = playingRole.getPlayerBean().getClub_id();
		if (clubId <= 0) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		Club club = ClubCache.getInstance().getClubById(clubId);
		if (club == null) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		int playerId = playingRole.getId();
		ClubMember cm = club.getMapMember().get(playerId);
		if (cm == null || cm.getAuth() == 0) { // 权限：0.普通成员 1.副会长 2.会长
			return ErrorCodeConstants.HALL_CLUB_NO_AUTH;
		}
		int nLev = club.getLevel() + 1;
		ClubUpTemplate upTemplate = ClubUpTemplateCache.getInstance().getTemplate(nLev);
		if (upTemplate == null) {
			return ErrorCodeConstants.HALL_CLUB_MAX_LEV;
		}
		if (upTemplate.getItemid() > 0 && upTemplate.getItemnum() > 0) {
			Map<Integer, Item> itemMap = ItemCache.getInstance().getItemTemplateKey(playerId);
			if (itemMap == null || !itemMap.containsKey(upTemplate.getItemid())) {
				return ErrorCodeConstants.HALL_NO_ITEM;
			}
			Item item = itemMap.get(upTemplate.getItemid());
			if (item.getCount() < upTemplate.getItemnum()) {
				return ErrorCodeConstants.HALL_NO_ITEM;
			}
			ItemManager.getInstance().useItem(playingRole, upTemplate.getItemid(), upTemplate.getItemnum());
		}
		club.setLevel(nLev);
		respMsg.level = nLev;
		respMsg.max_num = upTemplate.getMaxnum();
		ClubDaoHelper.getInstance().asyncUpdateClubBean(club);
		return 1;
	}

	/**
	 * 修改微信号
	 * 
	 * @param playingRole
	 * @param weixin
	 * @param respMsg
	 * @return
	 */
	public int modifyClubWeixin(PlayingRole playingRole, String weixin, S2CClubModifyWeixin respMsg) {
		int clubId = playingRole.getPlayerBean().getClub_id();
		if (clubId <= 0) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		Club club = ClubCache.getInstance().getClubById(clubId);
		if (club == null) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		int playerId = playingRole.getId();
		ClubMember cm = club.getMapMember().get(playerId);
		if (cm == null || cm.getAuth() == 0) { // 权限：0.普通成员 1.副会长 2.会长
			return ErrorCodeConstants.HALL_CLUB_NO_AUTH;
		}

		club.setCdrWeixin(weixin);
		ClubDaoHelper.getInstance().asyncUpdateClubBean(club);

		return 1;
	}

	/**
	 * 退出俱乐部
	 * 
	 * @param playingRole
	 * @return
	 */
	public int quitClub(PlayingRole playingRole) {
		int clubId = playingRole.getPlayerBean().getClub_id();
		if (clubId <= 0) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		Club club = ClubCache.getInstance().getClubById(clubId);
		if (club == null) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		int playerId = playingRole.getId();
		ClubMember cm = club.getMapMember().get(playerId);
		if (cm == null || cm.getAuth() == 2) { // 权限：0.普通成员 1.副会长 2.会长
			return ErrorCodeConstants.HALL_CLUB_NOT_EXIT;
		}

		club.getMapMember().remove(playingRole.getId());
		playingRole.getPlayerBean().setClub_id(0);

		ClubDaoHelper.getInstance().asyncDelClubMemberByPlayerId(playerId);
		// Send mail to 会长和副会长 CLUB_EXIT_MAIL_ID
		Set<Integer> setIds = new HashSet<>();
		for (ClubMember cmTemp : club.getMapMember().values()) {
			if (cmTemp.getAuth() != 0) {
				setIds.add(cmTemp.getPlayerId());
			}
		}
		Map<String, String> pars = new HashMap<>();
		pars.put("$1", playingRole.getPlayerBean().getName());
		pars.put("$2", DateKit.formateDateToStr(new Date()));
		MailManager.getInstance().asyncendMailToPlayerList(setIds.toArray(new Integer[0]), MailManager.CLUB_EXIT_MAIL_ID, pars, null);

		return 1;
	}

	/**
	 * 俱乐部成员列表
	 * 
	 * @param playingRole
	 * @param clubId
	 * @param p
	 * @param respMsg
	 * @return
	 */
	public int listClubMember(PlayingRole playingRole, int clubId, int p, S2CClubMember respMsg) {
		Club club = ClubCache.getInstance().getClubById(clubId);
		if (club == null) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		Collection<ClubMember> collect = club.getMapMember().values();
		List<ClubMember> listOnline = new ArrayList<>();
		List<ClubMember> listOffline = new ArrayList<>();
		for (ClubMember cm : collect) {
			if (PlayerOnlineCacheMng.getInstance().isOnline(cm.getPlayerId())) {
				listOnline.add(cm);
			} else {
				listOffline.add(cm);
			}
		}
		p = p < 1 ? 1 : p;
		List<ClubMemberDetail> listMemberDetail = new ArrayList<>();
		long now = System.currentTimeMillis();
		if (p == 1) {
			for (ClubMember cm : listOnline) {
				ClubMemberDetail cmd = new ClubMemberDetail();
				cmd.headimg = cm.getHeadimg();
				cmd.player_id = cm.getPlayerId();
				cmd.player_name = cm.getPlayerName();
				cmd.status = 1;
				cmd.downline_time = 0;
				cmd.credit_num = cm.getCredit_num();
				listMemberDetail.add(cmd);
			}
			for (ClubMember cm : listOffline) {
				ClubMemberDetail cmd = new ClubMemberDetail();
				cmd.headimg = cm.getHeadimg();
				cmd.player_id = cm.getPlayerId();
				cmd.player_name = cm.getPlayerName();
				cmd.status = 2;
				cmd.credit_num = cm.getCredit_num();
				int downline_time = 0;
				PlayerOfflineCache poc = PlayerOfflineManager.getInstance().getPlayerOfflineCache(cm.getPlayerId());
				if (poc != null && poc.getDownline_time() != null) {
					downline_time = (int) ((now - poc.getDownline_time().getTime()) / 1000);
				}
				cmd.downline_time = downline_time < 0 ? 0 : downline_time;
				listMemberDetail.add(cmd);
			}
		}
		Map<Integer, ClubApply> map = ClubCache.getInstance().getClubApplyMap(clubId);
		respMsg.club_id = clubId;
		respMsg.offline_num = listOffline.size();
		respMsg.online_num = listOnline.size();
		respMsg.apply_num = map == null ? 0 : map.size();
		respMsg.detail_list = listMemberDetail.toArray(new ClubMemberDetail[0]);

		return 1;
	}

	/**
	 * 俱乐部的金豆的出入明细
	 * 
	 * @param playingRole
	 * @param clubId
	 * @param respMsg
	 * @return
	 */
	public int jinDouDetailList(PlayingRole playingRole, int clubId, int p, S2CClubJinDouDetail respMsg) {
		Club club = ClubCache.getInstance().getClubById(clubId);
		if (club == null) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		List<ClubDonateDetail> list = ClubCache.getInstance().listJinDouDetailByClubId(clubId, p, 20);
		List<JinDouDetail> listJdd = new ArrayList<>();
		for (ClubDonateDetail cdd : list) {
			listJdd.add(packJinDouDetail(cdd));
		}
		respMsg.detail_list = listJdd.toArray(new JinDouDetail[0]);
		return 1;
	}

	/**
	 * 捐赠金豆进俱乐部
	 * 
	 * @param playingRole
	 * @param clubId
	 * @param donateNum
	 * @param respMsg
	 * @return
	 */
	public int donateClubInfo(PlayingRole playingRole, int clubId, long donateNum, S2CClubDonate respMsg) {
		clubId = playingRole.getPlayerBean().getClub_id();
		int playerId = playingRole.getId();
		Club club = ClubCache.getInstance().getClubById(clubId);
		if (club == null) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		logger.info("player club donate ,playerId={},clubId={},jinDouNum={}，current total jindou={}", playerId, clubId, donateNum, club.getJinDou());
		if (donateNum <= 0 || playingRole.getPlayerBean().getJin_dou() < donateNum) {
			return ErrorCodeConstants.HALL_NO_ENOUGH_JIN_DOU;
		}

		club.setJinDou(club.getJinDou() + donateNum);
		playingRole.getPlayerBean().setJin_dou(playingRole.getPlayerBean().getJin_dou() - donateNum);

		ClubDaoHelper.getInstance().asyncUpdateClubBean(club);

		ClubDonateDetail bean = new ClubDonateDetail();
		Date now = new Date();
		bean.setAct(1);
		bean.setActJinDou(donateNum);
		bean.setClubId(clubId);
		bean.setCreateTime(now);
		bean.setPlayerId(playerId);
		bean.setPlayerName(playingRole.getPlayerBean().getName());
		bean.setRetainJinDou(club.getJinDou());

		ClubCache.getInstance().addClubDonateDetail(bean);
		ClubDaoHelper.getInstance().asyncSaveClubDonateDetail(bean);

		respMsg.club_id = clubId;
		respMsg.jin_dou = club.getJinDou();
		respMsg.me_jin_dou = playingRole.getPlayerBean().getJin_dou();

		// send mail 金豆捐献成功，同时系统发送邮件到俱乐部会长和玩家自己
		Map<String, String> pars = new HashMap<>();
		pars.put("$1", DateKit.formateDateToStr(now));
		pars.put("$2", playingRole.getPlayerBean().getName());
		pars.put("$3", club.getName());
		pars.put("$4", donateNum + "");
		Integer[] playerIds = { playerId, club.getCdrId() };
		if (playerId == club.getCdrId()) {
			playerIds = new Integer[] { playerId };
		}

		MailManager.getInstance().asyncendMailToPlayerList(playerIds, MailManager.MAIL_DONATE_ID, pars, null);

		return 1;
	}

	/**
	 * 展示俱乐部信息
	 * 
	 * @param playingRole
	 * @param clubId
	 * @param respMsg
	 * @return
	 */
	public int showClubInfo(PlayingRole playingRole, int clubId, S2CClubInfo respMsg) {
		Club club = ClubCache.getInstance().getClubById(clubId);
		if (club == null) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		respMsg.club_info = packClubInfo(club, playingRole);
		return 1;
	}

	/**
	 * 申请加入俱乐部
	 * 
	 * @param playingRole
	 * @param clubId
	 * @param respMsg
	 * @return
	 */
	public int applyClub(PlayingRole playingRole, int clubId, S2CClubApply respMsg) {
		Club club = ClubCache.getInstance().getClubById(clubId);
		if (club == null) {
			return ErrorCodeConstants.HALL_CLUB_NO_FOUND;
		}
		if (playingRole.getPlayerBean().getClub_id() > 0) {
			return ErrorCodeConstants.HALL_CLUB_AMID;
		}
		int playerId = playingRole.getId();
		respMsg.club_id = clubId;
		respMsg.club_name = club.getName();
		respMsg.status = 1;
		if (ClubCache.getInstance().isApplyIngClub(clubId, playerId)) {
			return 1;
		}
		ClubUpTemplate ct = ClubUpTemplateCache.getInstance().getTemplate(club.getLevel());
		if (ct.getMaxnum() <= club.getNum()) {
			respMsg.status = 2; // 1.成功申请 2.人数已满 3.已经在俱乐部中
			return 1;
		}

		ClubApply clubApply = new ClubApply();
		clubApply.setClubId(clubId);
		clubApply.setCreateTime(new Date());
		clubApply.setPlayerId(playerId);

		ClubCache.getInstance().addClubApply(clubApply);
		ClubDaoHelper.getInstance().asyncSaveClubApply(clubApply);
		return 1;
	}

	/**
	 * 俱乐部列表
	 * 
	 * @param playingRole
	 * @param respMsg
	 */
	public void listClub(PlayingRole playingRole, int p, S2CClubList respMsg) {
		List<Club> list = ClubCache.getInstance().listClubByPage(p, 20);
		List<ClubInfo> listInfo = new ArrayList<>();
		for (Club club : list) {
			if (club.getDelFlag() != 0) {
				continue;
			}
			listInfo.add(packClubInfo(club, playingRole));
		}
		respMsg.club_info = listInfo.toArray(new ClubInfo[0]);
	}

	/**
	 * 发送短信
	 * 
	 * @param phone
	 */
	public int sendClubCode(int playerId, String phone) {
		if (!CommUtil.isPhone(phone)) {
			return ErrorCodeConstants.HALL_INVALID_PHONE;
		}

		ClubCodeBean clubCodeBean = ClubDao.getInstance().getClubCodeByPlayerId(playerId);
		Date now = new Date();
		if (clubCodeBean != null) {
			clubCodeBean.setPhone(phone);
			long lastTime = clubCodeBean.getSendTime().getTime();
			if (now.getTime() < (lastTime + 1800 * 1000L)) { // 30内有效 重发此号码
				// 重发此号码 send SMS
				clubCodeBean.setSendTime(now);
				ClubDaoHelper.getInstance().asyncUpdateClubCode(clubCodeBean);
				asyncSendSms(phone, clubCodeBean.getCode());
				return 1;
			} else {
				clubCodeBean.setIsValid(2);
				ClubDaoHelper.getInstance().asyncUpdateClubCode(clubCodeBean);
			}
		}
		String code = CommUtil.generateFourCode();
		clubCodeBean = new ClubCodeBean();
		clubCodeBean.setCode(code);
		clubCodeBean.setIsValid(0);
		clubCodeBean.setPhone(phone);
		clubCodeBean.setPlayerId(playerId);
		clubCodeBean.setSendTime(new Date());
		ClubDao.getInstance().addClubCode(clubCodeBean);
		// send SMS
		asyncSendSms(phone, code);
		return 1;
	}

	private void asyncSendSms(String phone, String code) {
		HallServer.executorService.execute(new Runnable() {
			@Override
			public void run() {
				YunPianUtil.sendSms(phone, "闽闽棋牌", code);
			}
		});
	}

	/**
	 * 随机俱乐部名称
	 * 
	 * @return
	 */
	public String randomClubName() {
		ClubNameTemplate ct = ClubNameTemplateCache.getInstance().getRandomTemplate();
		String clubName = "豆豆棋牌";
		clubName = ct == null ? clubName : ct.getName();
		logger.info(clubName);
		return clubName;
	}

	/**
	 * 创建俱乐部
	 * 
	 * @param playerId
	 * @param clubname
	 * @param phone
	 * @param code
	 */
	public int createClub(PlayingRole playingRole, C2SClubCreate clubReq, S2CClubCreate respMsg) {
		if (playingRole.getPlayerBean().getClub_id() > 0) {
			return ErrorCodeConstants.HALL_CLUB_AMID;
		}
		String clubname = clubReq.clubname;
		String code = clubReq.code;
		String phone = clubReq.phone;
		if (ClubCache.getInstance().isExistName(clubname)) {
			return ErrorCodeConstants.HALL_EXIST_NAME;
		}
		int playerId = playingRole.getId();
		ClubCodeBean clubCodeBean = ClubDao.getInstance().getClubCodeByPlayerId(playerId);
		if (clubCodeBean == null || !clubCodeBean.getCode().equals(code) || !clubCodeBean.getPhone().equals(phone)) {
			return ErrorCodeConstants.HALL_INVALID_CODE;
		}

		// 消耗道具
		ClubUpTemplate upTemplate = ClubUpTemplateCache.getInstance().getTemplate(1);
		if (upTemplate.getItemid() > 0 && upTemplate.getItemnum() > 0) {
			Map<Integer, Item> itemMap = ItemCache.getInstance().getItemTemplateKey(playerId);
			if (itemMap == null || !itemMap.containsKey(upTemplate.getItemid())) {
				return ErrorCodeConstants.HALL_NO_ITEM;
			}
			Item item = itemMap.get(upTemplate.getItemid());
			if (item.getCount() < upTemplate.getItemnum()) {
				return ErrorCodeConstants.HALL_NO_ITEM;
			}
			ItemManager.getInstance().useItem(playingRole, upTemplate.getItemid(), upTemplate.getItemnum());
		}
		Date now = new Date();
		Club club = new Club();
		int clubId = ClubCache.nextClubId();
		club.setCdrId(playerId);
		club.setCdrName(playingRole.getPlayerBean().getName());
		club.setCdrWeixin("");
		club.setCreateTime(now);
		club.setDelFlag(0);
		club.setDleTime(null);
		club.setFoundId(playerId);
		club.setFoundName(playingRole.getPlayerBean().getName());
		club.setJinDou(0L);
		club.setLevel(1);
		club.setLiveNessNum(0L);
		club.setName(clubname);
		club.setNum(1);
		club.setPhone(phone);
		club.setId(clubId);
		Map<Integer, ClubMember> mapMember = new ConcurrentHashMap<>();
		club.setMapMember(mapMember);

		// 权限：0.普通成员 1.副会长 2.会长
		addClubMember(club, playingRole.getPlayerBean(), 2);

		ClubCache.getInstance().addClub(club);

		clubCodeBean.setUseTime(now);
		clubCodeBean.setIsValid(1);
		ClubDaoHelper.getInstance().asyncUpdateClubCode(clubCodeBean);

		if (ClubNameTemplateCache.getInstance().removeUsedName(club.getName())) {
			ClubDaoHelper.getInstance().asyncSaveUsedName(club.getName());
		}

		// to player
		playingRole.getPlayerBean().setClub_id(clubId);
		PlayerDaoHelper.getInstance().asyncUpdatePlayerBean(playingRole);

		// DB
		ClubDaoHelper.getInstance().asyncSaveClub(club);

		respMsg.club_info = packClubInfo(club, playingRole);

		// send mail 创建俱乐部
		Map<String, String> params = new HashMap<>();
		params.put("$1", club.getName());
		MailManager.getInstance().sendMailSigleToPlayer(playerId, MailManager.MAIL_CREATE_CLUB_ID, params, null);

		return 1;
	}

	private ClubInfo packClubInfo(Club club, PlayingRole playingRole) {
		ClubInfo clubInfo = new ClubInfo();
		clubInfo.club_id = club.getId();
		clubInfo.name = club.getName();
		clubInfo.num = club.getMapMember().size();
		ClubUpTemplate upTemplate = ClubUpTemplateCache.getInstance().getTemplate(club.getLevel());
		clubInfo.max_num = upTemplate.getMaxnum();
		clubInfo.found_name = club.getCdrName();
		clubInfo.found_weixin = club.getCdrWeixin();
		clubInfo.liveness_num = club.getLiveNessNum();
		clubInfo.level = club.getLevel();
		clubInfo.rank = club.getRank();
		ClubMember cm = club.getMapMember().get(playingRole.getId());
		// 权限：4.非成员 3.已申请 0.普通成员 1.副会长 2.会长
		int auth = cm == null ? 4 : cm.getAuth();
		clubInfo.auth = auth;
		clubInfo.notice = club.getNotice();
		clubInfo.me_credit_num = cm == null ? 0 : cm.getCredit_num();
		clubInfo.me_jin_dou = playingRole.getPlayerBean().getJin_dou();
		clubInfo.jin_dou = club.getJinDou();
		return clubInfo;
	}

	public static void main(String[] args) {
		Map<String, String> params = new HashMap<>();
		Map<String, String> map_club = new HashMap<>();
		map_club.put("clubId", 1 + "");
		map_club.put("clubName", "闵闵棋牌");
		params.put("$OTHER", JSON.toJSONString(map_club));

		System.out.println(params.get("$OTHER"));
		Set<Integer> set = new HashSet<>();
		set.add(1);
		set.add(1);
		set.add(2);
		Integer[] list = set.toArray(new Integer[0]);
		for (int n : list) {
			System.out.println(n);
		}
	}

}
